﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Configuration;
using System.Data.SqlClient;
using System.Reflection;
using System.Data;

namespace CH.Study.ConsoleApp.ExpressionTree
{
    /// <summary>
    /// 数据提供集
    /// 负责构建表达式树 和 查询数据
    /// </summary>
    public class MsSqlQueryProvider : QueryExpressionProvider
    {

        public static readonly string ConnectionString = ConfigurationManager.AppSettings["MsSql2008"];
        public MsSqlQueryProvider()
        {
          
        }

        public override TResult Execute<TResult>(Expression expression) 
        {
            return (TResult)this.Execute(expression);
        }
        public override object Execute(Expression expression)
        {
            //这里是执行和翻译表达式树为TSQL语句
            object result;
            QueryExpressionSolution qes = new QueryExpressionSolution(new MsSqlQueryExpressionTranslator(), expression);
            if (qes.ExpressionType == QueryExpressionType.Select)
            {
                if (Type.GetTypeCode(qes.ReturnType) == TypeCode.Object)
                {
                    if (qes.IsPage)
                    {
                        SelectExpression se = expression as SelectExpression;
                        result = SqlHelper.ExecuteScalar(ConnectionString, CommandType.Text, qes.CountCmdText, qes.CountParameter.ToSqlParameterArray());
                        se.TotalRecord = (int)result;
                    }
                    //CommandBehavior.CloseConnection 在执行该命令时,如果关闭关联的 DataReader 对象,则关联的 Connection 对象也将关闭
                    //所以我们在读取完dr 的时候关闭dr 那么顺带也把数据库连接给关闭 具体可以看 QueryEnumerator 里面的方法Dispose()
                    SqlDataReader dr = SqlHelper.ExecuteReader(ConnectionString, CommandType.Text, qes.CmdText, qes.Parameter.ToSqlParameterArray()); ;
                    //返回一个可枚举器 可以枚举器里面包含了 枚举器 枚举器里面包含了查询出来的数据 dr
                    result = Activator.CreateInstance(typeof(QueryEnumerable<>).MakeGenericType(qes.ReturnType), BindingFlags.Instance | BindingFlags.Public, null, new object[] { dr }, null);
                }
                else
                {
                    result = SqlHelper.ExecuteScalar(ConnectionString, CommandType.Text, qes.CmdText, qes.Parameter.ToSqlParameterArray());
                }
            }
            else 
            {
                result = SqlHelper.ExecuteNonQuery(ConnectionString, CommandType.Text, qes.CmdText, qes.Parameter.ToSqlParameterArray());
            }
            return result;
        }

        public override QueryExpressionDebug GetQueryExpressionDebugMsg(Expression expression)
        {
            QueryExpressionSolution qes = new QueryExpressionSolution(new MsSqlQueryExpressionTranslator(), expression);
            return new QueryExpressionDebug() { CmdText = qes.CmdText, Parameter = qes.Parameter };
        }
    }
}
